import * as twgl from '../lib/twgl-full.module.js';
import { loadShaderFromFile, rand } from '../lib/tool-utils.js';

const main = async () => {
  // 设置attrib前缀
  twgl.setDefaults({ attribPrefix: 'a_' });
  const m4 = twgl.m4;
  const vs = await loadShaderFromFile('./shader/onPoint.vert');
  const fs = await loadShaderFromFile('./shader/onPoint.frag');
  const gl = document.querySelector('#c').getContext('webgl');

  const onePointProgramInfo = twgl.createProgramInfo(gl, [vs, fs]);

  // twgl中有默认的形状顶点数据
  const shapes = [
    // 创建立方体的顶点和索引。基于原点，(-size / 2, size / 2)
    twgl.primitives.createCubeBufferInfo(gl, 2),
    // 创建球体顶点。 radius：球体的半径。subdivisionsAxis：细分轴,subdivisionsHeight：细分高度,
    twgl.primitives.createSphereBufferInfo(gl, 1, 24, 12),
    // 创建 XZ 平面顶点  width：宽度,depth：深度,
    twgl.primitives.createPlaneBufferInfo(gl, 2, 2),
    // 创建截锥体的顶点，它类似于圆柱体
    // bottomRadius：底部半径，topRadius，顶部半径，height 高度，radialSubdivisions：径向细分 verticalSubdivisions：垂直细分
    twgl.primitives.createTruncatedConeBufferInfo(gl, 1, 0, 2, 24, 1),
  ];

  // 共享变量，绘制多个物体时的
  const camera = m4.identity();
  const view = m4.identity();
  const viewProjection = m4.identity();

  const textures = twgl.createTextures(gl, {
    // A 2x2 pixel texture from a JavaScript array
    // 来自 JavaScript 数组的 2x2 像素纹理
    checker: {
      mag: gl.NEAREST,
      min: gl.LINEAR,
      src: [255, 255, 255, 255, 192, 192, 192, 255, 192, 192, 192, 255, 255, 255, 255, 255],
    },
  });

  const twoDTextures = [textures.checker];

  // 渲染的对象
  const objects = []; // {translation,ySpeed,zSpeed,uniforms}
  const drawObjects = []; //{programInfo,bufferInfo,uniforms}
  for (let ii = 0; ii < 10; ii++) {
    let uniforms, programInfo, shape;
    shape = shapes[ii % shapes.length];
    programInfo = onePointProgramInfo;
    uniforms = {
      // 环境光？
      u_diffuseMult: [0.8, 0.48, 0.63, 1],
      // 环境颜色
      u_diffuse: twoDTextures[0],
      u_viewInverse: camera,
      u_world: m4.identity(),
      u_worldInverseTranspose: m4.identity(),
      u_worldViewProjection: m4.identity(),
    };
    drawObjects.push({
      programInfo: programInfo,
      bufferInfo: shape,
      uniforms: uniforms,
    });
    objects.push({
      translation: [rand(-10, 10), rand(-10, 10), rand(-10, 10)],
      ySpeed: rand(0.1, 0.3),
      zSpeed: rand(0.1, 0.3),
      uniforms: uniforms,
    });
  }

  const render = (time) => {
    time *= 0.001;
    twgl.resizeCanvasToDisplaySize(gl.canvas);
    gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);

    gl.enable(gl.DEPTH_TEST);
    gl.enable(gl.BLEND);
    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    //-------------处理 投影矩阵，视图矩阵，世界矩阵---------
    const fov = (30 * Math.PI) / 180; // 30度
    const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
    const zNear = 0.5; //轴0.5-10可见
    const zFar = 100;
    // 投影矩阵和四个参数有关，1. 视锥体角度，2.投影平面的宽高比，3. 近处距离，4.远处距离
    const projection = m4.perspective(fov, aspect, zNear, zFar);

    // 相机矩阵和三个参数有关 1. 相机的坐标，2. 看向点的坐标，3. 相机向上坐标
    const eye = [20, 4, 0];
    const target = [0, 0, 0];
    const up = [0, 1, 0];
    m4.lookAt(eye, target, up, camera);

    // 视图矩阵
    m4.inverse(camera, view);
    // 视图投影矩阵
    m4.multiply(projection, view, viewProjection);

    objects.forEach(function (obj) {
      const objUniforms = obj.uniforms;
      const world = objUniforms.u_world;
      m4.identity(world);
      m4.rotateY(world, time * obj.ySpeed, world);
      m4.rotateZ(world, time * obj.zSpeed, world);
      m4.translate(world, obj.translation, world);
      m4.rotateX(world, time, world);
      m4.transpose(m4.inverse(world, objUniforms.u_worldInverseTranspose), objUniforms.u_worldInverseTranspose);
      m4.multiply(viewProjection, objUniforms.u_world, objUniforms.u_worldViewProjection);
    });

    twgl.drawObjectList(gl, drawObjects);

    requestAnimationFrame(render);
  };
  requestAnimationFrame(render);
};
main();
